
import com.jayway.jsonpath.internal.function.numeric.AbstractAggregation;
import com.myrest.provider.poi.work.entities.user.ESUser;
import com.mytest.provider.es.EsApplication;
import com.mytest.provider.es.mapper.ElasticRepository;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.range.AbstractRangeBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.metrics.avg.InternalAvg;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest(classes= EsApplication.class)
public class estest {

    @Autowired
    private ElasticsearchTemplate estemplate;

    @Autowired
    private ElasticRepository elasticRepository;

    /**
     * 生成索引库
     */
    @Test
    public void test01(){
        estemplate.createIndex(ESUser.class);
    }

    /**
     * 生成索引库的映射，生成文档
     */
    @Test
    public void test02(){
        estemplate.putMapping(ESUser.class);
    }

    /**
     * 新增
     */
    @Test
    public void test03(){
        ESUser esUser = new ESUser(1L,"王朗","123456","王司徒",86);
        elasticRepository.save(esUser);
    }

    @Test
    public void indexList() {
        List<ESUser> list = new ArrayList<>();
        list.add(new ESUser(1L,"王朗","123456","王司徒",86));
        list.add(new ESUser(2L,"王允","456789","王司徒",56));
        // 接收对象集合，实现批量新增
        elasticRepository.saveAll(list);
    }

    @Test
    public void query(){
        // 查询全部，并按照年龄降序排序
        Iterable<ESUser> items = this.elasticRepository.findAll(Sort.by("sex").descending());
        for (ESUser item : items) {
            System.out.println("item = " + item);
        }
    }

    @Test
    public void indexListAdd() {
       /* List<ESUser> list = new ArrayList<>();
        list.add(new ESUser(1L,"王朗","123456","王司徒",86));
        list.add(new ESUser(2L,"王允","456789","王司徒",56));
        // 接收对象集合，实现批量新增
        elasticRepository.saveAll(list);*/
    }

//    @Test
//    public void queryByPriceBetween(){
//        List<ESUser> list = this.elasticRepository.findBySexBetween(2000.00, 3500.00);
//        for (ESUser user : list) {
//            System.out.println("user = " + user);
//        }
//    }

    @Test
    public void search(){
        //查询条件构造器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        //给条件构造器添加查询条件,QueryBuildersl来生成一个查询
        queryBuilder.withQuery(QueryBuilders.matchQuery("username","王朗"));
//         queryBuilder.withPageable();
        //搜索结果,把查询条件构造器中的查询条件进行build构造,创建成查询条件对象
//        page : 不知道有没有加queryBuilder.withPageable();所以默认是分页查询,往大了去加
        Page<ESUser> search = this.elasticRepository.search(queryBuilder.build());
        List<ESUser> items = search.getContent();
        items.forEach(user -> {
            System.out.println("user:"+user);
        });
    }

    @Test
    public void search02(){
        //查询条件构造器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.matchQuery("username","王朗").operator(Operator.AND));
        queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
        Page<ESUser> search = this.elasticRepository.search(queryBuilder.build());
        List<ESUser> items = search.getContent();
        items.forEach(item -> {
            System.out.println("item:"+item);
        });
    }

    @Test
    public void search03(){
        //查询条件构造器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.matchQuery("username","王朗").operator(Operator.AND));
        queryBuilder.withPageable(PageRequest.of(0,2));
        Page<ESUser> search = this.elasticRepository.search(queryBuilder.build());
        List<ESUser> items = search.getContent();
        items.forEach(item -> {
            System.out.println("item:"+item);
        });
    }

    @Test
    public void search04(){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//        添加聚合条件
        queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("nickName"));
//        聚合的结果在search中,但要获取结果,就要强转为AggregatedPage
        AggregatedPage<ESUser> search = (AggregatedPage<ESUser>) this.elasticRepository.search(queryBuilder.build());
//        根据debug得知brands是StringTerms类型的,要强转
//        由于参与聚合的字段类型是String,所以聚合结果纳入StringTerms,如果是long ,就是LongTerms
        StringTerms brands = (StringTerms) search.getAggregation("brands");
        List<StringTerms.Bucket> buckets = brands.getBuckets();
        buckets.forEach(bucket -> {
            System.out.println(bucket.getKeyAsString());
            System.out.println(bucket.getDocCount());
        });
    }


    @Test
    public void search05(){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//        添加聚合条件
        queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("nickName")
        .subAggregation(AggregationBuilders.avg("ag").field("price")));
//        聚合的结果在search中,但要获取结果,就要强转为AggregatedPage
        AggregatedPage<ESUser> search = (AggregatedPage<ESUser>) this.elasticRepository.search(queryBuilder.build());
//        根据debug得知brands是StringTerms类型的,要强转
//        由于参与聚合的字段类型是String,所以聚合结果纳入StringTerms,如果是long ,就是LongTerms
        StringTerms brands = (StringTerms) search.getAggregation("brands");
        List<StringTerms.Bucket> buckets = brands.getBuckets();
        buckets.forEach(bucket -> {
            //        获取度量聚合,转为map
            InternalAvg ag = (InternalAvg) bucket.getAggregations().asMap().get("ag");
            System.out.println(bucket.getKeyAsString());
            System.out.println(bucket.getDocCount());
            System.out.println(ag.getValue());
        });
    }
}
